package com.dzjcloud.dzj.gateway.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.dzjcloud.dzj.common.core.exception.HandleException;
import com.dzjcloud.dzj.gateway.dto.Gateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <h3>dzj-cloud</h3>
 * <p>动态路由实现类</p>
 *
 * @author : DongZeJian
 * @date : 2023-04-11 10:55
 **/
@Service
@Slf4j
public class DynamicRouteServiceImpl  implements ApplicationEventPublisherAware {

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher publisher;

    @Autowired
    private RouteDefinitionRepository routeDefinitionRepository;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    /**
     *  刷新所有路由
     *
     * @param gateways
     */
    public void refresh(List<Gateway> gateways){

        // 删除旧路由111
        routeDefinitionRepository
                .getRouteDefinitions()
                .flatMap(v -> routeDefinitionWriter.delete(Mono.just(v.getId())))
                .collectList()
                .doOnNext(v -> {
                    if (CollUtil.isNotEmpty(gateways)) {
                        for (Gateway gateway : gateways) {
                            if (StrUtil.isNotBlank(gateway.getFromUrl()) && StrUtil.isNotBlank(gateway.getToUrl())) {
                                RouteDefinition routeDefinition=new RouteDefinition();
                                routeDefinition.setId(gateway.getFromUrl());
                                routeDefinition.setUri(URI.create(gateway.getToUrl()));
                                routeDefinition.setOrder(gateway.getPriority());
                                PredicateDefinition predicateDefinition=new PredicateDefinition();
                                predicateDefinition.setName("Path");
                                predicateDefinition.getArgs().put("pattern",gateway.getFromUrl());
                                routeDefinition.getPredicates().add(predicateDefinition);

                                //去除转发路由前缀  设置为1就去除 https://blog.csdn.net/guaniuqaq/article/details/88232906
                                FilterDefinition filterDefinition = new FilterDefinition();
                                filterDefinition.setName("StripPrefix");
                                Map<String, String> filterParams = new HashMap<>();
                                filterParams.put(StripPrefixGatewayFilterFactory.PARTS_KEY, String.valueOf(1));
                                filterDefinition.setArgs(filterParams);
                                routeDefinition.setFilters(Collections.singletonList(filterDefinition));
                                add(routeDefinition);
                            }
                        }
                    }
                })
                .subscribe();




    }

    //增加路由
    public String add(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }

    //更新路由
    public String update(RouteDefinition definition) {
        try {
            delete(definition.getId());
        } catch (Exception e) {
            return "update fail, not find route routeId: " + definition.getId();
        }
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "success";
        } catch (Exception e) {
            return "update route  fail";
        }
    }

    //删除路由
    public boolean delete(String id) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.toString());
            return false;
        }
        return true;
    }
}
